#include <qqtmodbusmanager.h>

#include "qqtcore.h"

QQtModbusSession::QQtModbusSession ( QObject* parent ) :
    QObject ( parent )
{
    m_pTimer = new QTimer ( this );
    m_pTimer->setSingleShot ( true );
    m_pTimer->setInterval ( 10000 );
}

QQtModbusSession::~QQtModbusSession() {}

void QQtModbusSession::setTimeOut ( int timeout )
{
    m_pTimer->setInterval ( timeout );
}

QTimer* QQtModbusSession::getTimer()
{
    return m_pTimer;
}

int QQtModbusSession::getModbusServerAddress()
{
    return m_serverAddress;
}

void QQtModbusSession::setModbusServerAddress ( int serverAddress )
{
    m_serverAddress = serverAddress;
}

QModbusRequest& QQtModbusSession::modbusRequest()
{
    return mModbusRequest; //raw
}

QModbusDataUnit& QQtModbusSession::modbusDataUnit()
{
    return mModbusDataUnit; //common, unit
}

QModbusDataUnit& QQtModbusSession::modbusWriteDataUnit()
{
    return mModbusWriteDataUnit;
}

QModbusReply* QQtModbusSession::getModbusReply()
{
    return m_pModbusReply;
}

void QQtModbusSession::setModbusReply ( QModbusReply* reply )
{
    m_pModbusReply = reply;
}

QString QQtModbusSession::getModbusSessionName()
{
    return m_strSessionName;
}

void QQtModbusSession::setModbusSessionName ( QString strSessionName )
{
    m_strSessionName = strSessionName;
}

QQtModbusSessionManager::QQtModbusSessionManager ( QObject* parent ) :
    QObject ( parent ) {}

QQtModbusSessionManager::~QQtModbusSessionManager() {}

QString QQtModbusSessionManager::addModbusSession ( QQtModbusSession* session )
{
    if ( !session )
        return QString();

    m_listModbusSession.push_back ( session );
    return session->getModbusSessionName();
}

void QQtModbusSessionManager::removeModbusSession ( QQtModbusSession* session )
{
    if ( !session )
        return;

    m_listModbusSession.removeOne ( session );
}

QQtModbusSession* QQtModbusSessionManager::newModbusSession()
{
    QUuid uuid = QUuid::createUuid();
    QQtModbusSession* session = new QQtModbusSession ( this );
    session->setModbusSessionName ( uuid.toString() );
    m_listModbusSession.push_back ( session );
    return session;
}

int QQtModbusSessionManager::getSessionCount() const
{
    return m_listModbusSession.count();
}

int QQtModbusSessionManager::getRequestServerAddressByReply ( QModbusReply* reply )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusReply() == reply )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return 0;

    return s0->getModbusServerAddress();
}

QString QQtModbusSessionManager::getSessionNameByReply ( QModbusReply* reply )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusReply() == reply )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return QString();

    return s0->getModbusSessionName();
}


QQtModbusSession* QQtModbusSessionManager::getSessionByReply ( QModbusReply* reply )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusReply() == reply )
        {
            s0 = s1;
            break;
        }
    }

    return s0;
}

QModbusReply* QQtModbusSessionManager::getReplyHandlerByServerAddress ( int serverAddress )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusServerAddress() == serverAddress )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return NULL;

    return s0->getModbusReply();
}

QString QQtModbusSessionManager::getSessionNameByServerAddress ( int serverAddress )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusServerAddress() == serverAddress )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return QString();

    return s0->getModbusSessionName();
}

QQtModbusSession* QQtModbusSessionManager::getSessionByServerAddress ( int serverAddress )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusServerAddress() == serverAddress )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return NULL;

    return s0;
}

QModbusReply* QQtModbusSessionManager::getReplyHandlerBySessionName ( QString strSessionName )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusSessionName() == strSessionName )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return NULL;

    return s0->getModbusReply();
}

int QQtModbusSessionManager::getRequestServerAddressBySessionName ( QString strSessionName )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusSessionName() == strSessionName )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return 0;

    return s0->getModbusServerAddress();
}

QQtModbusSession* QQtModbusSessionManager::getSessionBySessionName ( QString strSessionName )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getModbusSessionName() == strSessionName )
        {
            s0 = s1;
            break;
        }
    }

    return s0;
}

QModbusReply* QQtModbusSessionManager::getReplyHandlerByTimer ( QTimer* timer )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getTimer() == timer )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return NULL;

    return s0->getModbusReply();
}

int QQtModbusSessionManager::getRequestServerAddressByTimer ( QTimer* timer )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getTimer() == timer )
        {
            s0 = s1;
            break;
        }
    }

    if ( !s0 )
        return NULL;

    return s0->getModbusServerAddress();
}

QQtModbusSession* QQtModbusSessionManager::getSessionByTimer ( QTimer* timer )
{
    QQtModbusSession* s0 = NULL;
    QListIterator<QQtModbusSession*> itor ( m_listModbusSession );

    while ( itor.hasNext() )
    {
        QQtModbusSession* s1 = itor.next();

        if ( s1->getTimer() == timer )
        {
            s0 = s1;
            break;
        }
    }

    return s0;
}

QModbusReply* QQtModbusSessionManager::getReplyHandler ( QQtModbusSession* session )
{
    if ( !session )
        return NULL;

    return session->getModbusReply();
}

int QQtModbusSessionManager::getRequestServerAddress ( QQtModbusSession* session )
{
    if ( !session )
        return 0;

    return session->getModbusServerAddress();
}

QString QQtModbusSessionManager::getSessionName ( QQtModbusSession* session )
{
    if ( !session )
        return QString();

    return session->getModbusSessionName();
}


QQtModbusManager::QQtModbusManager ( QObject* parent ) : QModbusClient ( parent )
{
    manager = new QQtModbusSessionManager ( this );

    connect ( this, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( errorOccurred ( QModbusDevice::Error ) ) );

    connect ( this, SIGNAL ( stateChanged ( QModbusDevice::State ) ),
              this, SLOT ( stateChanged ( QModbusDevice::State ) ) );

    connect ( this, SIGNAL ( timeoutChanged ( int ) ),
              this, SLOT ( timeoutChanged ( int ) ) );
}

QQtModbusSessionManager* QQtModbusManager::getModbusSessionManager()
{
    return manager;
}

QQtModbusSession* QQtModbusManager::sendRawRequest ( const QModbusRequest& request, int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusRequest() = request;
    session->setModbusServerAddress ( serverAddress );

    QModbusRequest& netRequest = session->modbusRequest();
    QModbusReply* reply = QModbusClient::sendRawRequest ( netRequest, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

QQtModbusSession* QQtModbusManager::sendReadRequest ( const QModbusDataUnit& read, int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusDataUnit() = read;
    session->setModbusServerAddress ( serverAddress );

    QModbusDataUnit& netRequest = session->modbusDataUnit();
    QModbusReply* reply = QModbusClient::sendReadRequest ( netRequest, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

QQtModbusSession* QQtModbusManager::sendWriteRequest ( const QModbusDataUnit& write, int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusWriteDataUnit() = write;
    session->setModbusServerAddress ( serverAddress );

    QModbusDataUnit& netRequest = session->modbusWriteDataUnit();
    QModbusReply* reply = QModbusClient::sendWriteRequest ( netRequest, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

QQtModbusSession* QQtModbusManager::sendReadWriteRequest ( const QModbusDataUnit& read, const QModbusDataUnit& write,
                                                           int serverAddress )
{
    QQtModbusSession* session = manager->newModbusSession();
    session->modbusDataUnit() = read;
    session->modbusWriteDataUnit() = write;
    session->setModbusServerAddress ( serverAddress );

    QModbusDataUnit& netRequest = session->modbusDataUnit();
    QModbusDataUnit& netRequest2 = session->modbusWriteDataUnit();
    //reply里面怎么体现写的？不用体现对吧？
    QModbusReply* reply = QModbusClient::sendReadWriteRequest ( netRequest, netRequest2, serverAddress );
    session->setModbusReply ( reply ); //发起get请求
    /*下面关联信号和槽*/

    /*下载完成后开始一阵一阵堆取数据*/
    connect ( reply, SIGNAL ( finished() ),
              this, SLOT ( localReplyFinished() ) );
    connect ( reply, SIGNAL ( errorOccurred ( QModbusDevice::Error ) ),
              this, SLOT ( localReplyErrorOccurred ( QModbusDevice::Error ) ) );

    QTimer* timer = session->getTimer();
    connect ( timer, SIGNAL ( timeout() ),
              this, SLOT ( localReplyTimeOut() ) ); //超时信号
    timer->start();

    return session;
}

void QQtModbusManager::errorOccurred ( QModbusDevice::Error error )
{
    pline() << error;
}

void QQtModbusManager::stateChanged ( QModbusDevice::State state )
{
    pline() << state;
}

void QQtModbusManager::timeoutChanged ( int newTimeout )
{
    pline() << newTimeout;
}

void QQtModbusManager::localReplyFinished()
{
    QModbusReply* reply = ( QModbusReply* ) sender();
    //pline() << reply;

    //clear resource
    QQtModbusSession* s0 = manager->getSessionByReply ( reply );
    //pline() << reply << s0;

    if ( !s0 )
        return;

    //pline() << s0->getModbusReply() << s0->getTimer();
    emit replyFinished ( s0 );

    s0->getTimer()->stop();
    s0->getModbusReply()->deleteLater();
    manager->removeModbusSession ( s0 );
}

void QQtModbusManager::localReplyTimeOut()
{
    QTimer* timer = ( QTimer* ) sender();
    pline() << timer;

    QQtModbusSession* s0 = manager->getSessionByTimer ( timer );

    if ( !s0 )
        return;

    emit replyTimeOut ( s0 ); //请求失败
    //s0->getModbusReply()->abort();
    s0->getModbusReply()->deleteLater();
    manager->removeModbusSession ( s0 );
}

void QQtModbusManager::localReplyErrorOccurred ( QModbusDevice::Error )
{
    QModbusReply* reply = ( QModbusReply* ) sender();
    //pline() << reply;
    QQtModbusSession* session = manager->getSessionByReply ( reply );
    if ( !session )
        return;
    emit replyErrorOccurred ( session );
    session->getModbusReply()->deleteLater();
    manager->removeModbusSession ( session );
}
